package edu.gatech.spacetraderteam3.view;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;

import edu.gatech.spacetraderteam3.debug.Debug;

/**
 * A class that represents a basic GUI component
 * @author Alexander Ikonomidis
 * @version 1.0
 */
public abstract class SGGComponent {
    protected enum Direction {
        NORTH,
        SOUTH,
        EAST,
        WEST;
    }

    /**
     * Values used to draw a component on the screen
     */
    protected int originX, originY, offX, offY, wid, hei;

    /**
     * The boundary of the component
     */
    protected Rectangle bound;

    /**
     * The component's color
     */
    protected Color color = Color.BLACK;

    /**
     * The component's event listener/handler
     */
    protected SGGEventListener sggEventListener;

    /**
     * boolean values for if the component is visible and/or in focus
     */
    protected boolean focusable = true, visible = true;

    /**
     * SGGComponent constructor. Sets width, height, bounds and listeners
     * @param wid Width of the component 
     * @param high Height of the component
     */
    protected SGGComponent(int wid, int high) {
        this.wid = wid;
        this.hei = high;
        bound = new Rectangle(originX, originY, wid, high);
        sggEventListener = new SGGEventListener() {
            public void doEvent(SGGEvent sgge) {
                Debug.write(sgge, 2);
            }
        };
    }

    /**
     * Paints component
     * @param g Graphics component to paint on
     */
    public void paint(Graphics2D g) {
        if (visible) {
            doPaint(g);
        }
    }

    /**
     * Abstract paint method
     * @param g Graphics component to paint on
     */
    public abstract void doPaint(Graphics2D g);

    /**
     * Method that defines what occurs when clicked
     * @param p Point where the mouse was clicked
     */
    protected void doClick(Point p) { // $codepro.audit.disable emptyMethod
    }

    /**
     * Method that defines what occurs when a specific key is pressed
     * @param k Key that is pressed
     */
    protected void doKey(KeyEvent k) {// $codepro.audit.disable emptyMethod
    }

    /**
     * Method that defines what occurs when a specific key is released
     */
    protected void doRelease() {// $codepro.audit.disable emptyMethod
    }

    /**
     * Method that defines what occurs when component loses focus
     */
    protected void loseFocus() {// $codepro.audit.disable emptyMethod
    }

    /**
     * Setter for whether the component is in focus
     * @param focusable Whether the component is in focus
     */
    protected void setFocusable(boolean focusable) {
        this.focusable = focusable;
    }

    /**
     * Getter for whether the component is visible
     * @return If visible
     */
    public boolean isVisible() {
        return visible;
    }

    /**
     * Setter for visibility
     * @param visible Visibility to set
     */
    protected void setVisible(boolean visible) {
        this.visible = visible;
    }

    /**
     * Requests repaint through the window manager
     */
    protected void repaint() {
        SGGWM.requestRepaint(); // change this to only repaint the rectangle the object occupies.
    }

    /**
     * Setter for the offsets. Sets bound location to reflect offset. 
     * @param offX X offset
     * @param offY Y offset
     */
    protected void setOffset(int offX, int offY) {
        this.offX = offX;
        this.offY = offY;
        bound.setLocation(originX + offX, originY + offY);
    }

    /**
     * Sets the Origin of the component. Sets bound location to reflect new origin
     * @param originX X coordinate of the origin
     * @param originY Y coordinate of the origin
     */
    protected void setOrigin(int originX, int originY) {
        this.originX = originX;
        this.originY = originY;
        bound.setLocation(originX + offX, originY + offY);
    }

    /**
     * Sets the size of the component. Updates bound to reflect changed
     * @param wid Width of the component
     * @param high Height of the component
     */
    protected void setDimensions(int wid, int high) {
        this.wid = wid;
        this.hei = high;
        bound.setSize(wid, high);
    }

    /**
     * Getter for the component's X value
     * @return X value
     */
    public int getX() {
        return originX + offX;
    }

    /**
     * Getter for the component's Y value
     * @return Y value
     */
    public int getY() {
        return originY + offY;
    }

    /**
     * Getter for the component's width
     * @return Width
     */
    public int getWidth() {
        return wid;
    }

    /**
     * Getter for the component's Height
     * @return Height
     */
    public int getHeight() {
        return hei;
    }

    /**
     * Checks to see if bounds contains a point
     * @param p Point to check
     * @return Whether point is contained in bounds
     */
    public boolean contains(Point p) {
        return focusable && visible && bound.contains(p);
    }

    /**
     * Setter for the component color
     * @param color Color of component
     */
    public void setColor(Color color) {
        this.color = color;
    }

    /**
     * Getter for the color of the component
     * @return The color of the component
     */
    public Color getColor() {
        return color;
    }

    /**
     * Setter for the components Event Listener
     * @param sggEventListener Event Listener the component listens on 
     */
    public void setSGGEventListener(SGGEventListener sggEventListener) {
        this.sggEventListener = sggEventListener;
    }
}
